// DlgPickUser.cpp : implementation file
//

#include "stdafx.h"
#include "Celsus.h"
#include "DlgPickUser.h"
#include "DlgAddLDAPUser.h"
#include "DlgEditUser.h"

// CDlgPickUser dialog

IMPLEMENT_DYNAMIC(CDlgPickUser, CDialog)

CDlgPickUser::CDlgPickUser(CWnd* pParent /*=NULL*/)
	: CDialog(CDlgPickUser::IDD, pParent)
	, m_szFind(_T(""))
{
	m_nCurrentSort = USR_EMAIL;
	m_bSortAscending = TRUE;
	m_nType = PICK_TYPE_USER;
	m_bAdd = FALSE;
	m_szSort = _T("name");
}

CDlgPickUser::~CDlgPickUser()
{
}

void CDlgPickUser::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST_USERS, m_ctrlUsersList);
	DDX_Text(pDX, IDC_EDIT_FIND, m_szFind);
}


BEGIN_MESSAGE_MAP(CDlgPickUser, CDialog)
	ON_NOTIFY(NM_DBLCLK, IDC_LIST_USERS, &CDlgPickUser::OnNMDblclkListUsers)
	ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_USERS, &CDlgPickUser::OnLvnItemchangedListUsers)
	ON_NOTIFY(HDN_ITEMCLICK, 0, &CDlgPickUser::OnHdnItemclickListUsers)
	ON_NOTIFY(LVN_ODFINDITEM, IDC_LIST_USERS, &CDlgPickUser::OnLvnOdfinditemListUsers)
	ON_NOTIFY(LVN_GETDISPINFO, IDC_LIST_USERS, &CDlgPickUser::OnLvnGetdispinfoListUsers)
	ON_BN_CLICKED(IDC_BUTTON_FIND, &CDlgPickUser::OnBnClickedButtonFind)
	ON_BN_CLICKED(IDC_BUTTON_ADD_USER, &CDlgPickUser::OnBnClickedButtonAddUser)
END_MESSAGE_MAP()


// CDlgPickUser message handlers

BOOL CDlgPickUser::OnInitDialog()
{
	CDialog::OnInitDialog();

	// show wait
	CWaitCursor wait;

	// disable ok
	GetDlgItem( IDOK )->EnableWindow( FALSE );
	SetDefaultButton( IDC_BUTTON_FIND );
	
	// set extended styles
	m_ctrlUsersList.SetExtendedStyle( LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_SUBITEMIMAGES | LVS_EX_INFOTIP  );

	// insert columns
	m_ctrlUsersList.InsertColumn( USR_ACTIVATED, _T(""), LVCFMT_CENTER,  18, USR_ACTIVATED );
	m_ctrlUsersList.InsertColumn( USR_EMAIL, _T("EMail"), LVCFMT_LEFT,  200, USR_EMAIL );
	// show optional
	if( m_nType == PICK_TYPE_STAFF )
	{
		// add columns
		m_ctrlUsersList.InsertColumn( USR_LAN_ID, _T("LAN ID"), LVCFMT_LEFT, 0, USR_NAME );
		m_ctrlUsersList.InsertColumn( USR_NAME, _T("Name"), LVCFMT_LEFT, 150, USR_NAME );
		m_ctrlUsersList.InsertColumn( USR_COMPANY, _T("Library"), LVCFMT_LEFT, 200, USR_COMPANY );
		// set title
		SetWindowText( _T("Pick Staff") );
	}
	else if( m_nType == PICK_TYPE_ILL )
	{
		// set sort
		m_szSort = _T("email");
		// add column
		m_ctrlUsersList.InsertColumn( USR_LAN_ID, _T("LAN ID"), LVCFMT_LEFT, 0, USR_NAME );
		m_ctrlUsersList.InsertColumn( USR_NAME, _T("Name"), LVCFMT_LEFT, 0, USR_NAME );
		m_ctrlUsersList.InsertColumn( USR_COMPANY, _T("Company"), LVCFMT_LEFT, 200, USR_COMPANY );
		// set title
		SetWindowText( _T("Pick External ILL") );
	}
	else
	{
		// add columns
		if( appConfig.m_LDAP.bUseLDAPLogons )
			m_ctrlUsersList.InsertColumn( USR_LAN_ID, _T("LAN ID"), LVCFMT_LEFT, 100, USR_NAME );
		else
			m_ctrlUsersList.InsertColumn( USR_LAN_ID, _T("LAN ID"), LVCFMT_LEFT, 0, USR_NAME );
		m_ctrlUsersList.InsertColumn( USR_NAME, _T("Name"), LVCFMT_LEFT, 150, USR_NAME );
		m_ctrlUsersList.InsertColumn( USR_COMPANY, _T("Company"), LVCFMT_LEFT, 200, USR_COMPANY );
	}

	// hide add button
	if( !m_bAdd )
		GetDlgItem( IDC_BUTTON_ADD_USER )->ShowWindow( SW_HIDE );

	// fill list
	FillList();

	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

void CDlgPickUser::OnOK()
{
	if( m_ctrlUsersList.GetSelectedCount() < 1 )
	{
		AfxMessageBox( _T("Please select account before proceding.") );
		return;
	}

	CDialog::OnOK();
}

void CDlgPickUser::OnCancel()
{
	// TODO: Add your specialized code here and/or call the base class

	CDialog::OnCancel();
}

void CDlgPickUser::OnBnClickedButtonFind()
{
	// update data
	UpdateData();

	// build search
	if( m_nType == PICK_TYPE_STAFF )
	{
		m_szFilter.Format( _T("(name LIKE '%%%s%%' OR email LIKE '%%%s%%')"), m_szFind, m_szFind );
	}
	else if( m_nType == PICK_TYPE_ILL )
	{
		m_szFilter.Format( _T("(email LIKE '%%%s%%' OR company LIKE '%%%s%%')"), m_szFind, m_szFind );
	}
	else
	{
		m_szFilter.Format( _T("(lan_id LIKE '%%%s%%' OR name LIKE '%%%s%%' OR email LIKE '%%%s%%' OR company LIKE '%%%s%%')"), m_szFind, m_szFind, m_szFind, m_szFind );
	}
	// fill list
	FillList();
}

void CDlgPickUser::OnNMDblclkListUsers(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	//return result
	*pResult = 0;
	// do ok;
	OnOK();
}

void CDlgPickUser::OnLvnItemchangedListUsers(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);

	// get new selection
	if( pNMLV->uNewState & LVIS_SELECTED )
	{
		m_szEmail = m_ctrlUsersList.GetItemText( pNMLV->iItem, USR_EMAIL );
		m_szName = m_ctrlUsersList.GetItemText( pNMLV->iItem, USR_NAME );
		m_szCompany = m_ctrlUsersList.GetItemText( pNMLV->iItem, USR_COMPANY );
		// enable ok
		GetDlgItem( IDOK )->EnableWindow();
		SetDefaultButton( IDOK );
	}
	//return result
	*pResult = 0;
}

void CDlgPickUser::OnLvnGetdispinfoListUsers(NMHDR *pNMHDR, LRESULT *pResult)
{
	NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
	// TODO: Add your control notification handler code here
	*pResult = 0;

    // Create a pointer to the item
    LV_ITEM* pItem = &(pDispInfo)->item;

    // Which item number?
    INT nItemId = pItem->iItem;

	// get request
	ASSERT( nItemId <= m_aPickList.GetCount() );
	PICKLIST currentRequest;
	currentRequest = m_aPickList.GetAt( nItemId );

	// Does the list need text information?
	if( pItem->mask & LVIF_TEXT )
	{
		TRACE( _T("SubItem = %d\n"), pItem->iSubItem );

		// set text
		CString szText;
		// set item id
		switch( pItem->iSubItem )		
		{
		case USR_ACTIVATED:
			if( currentRequest.nActivated )
				szText = _T("A");
			else
				szText = _T("");
			break;
		case USR_EMAIL:
			szText = currentRequest.szUserEmail;			
			break;
		case USR_LAN_ID:
			szText = currentRequest.szUserLANID;			
			break;
		case USR_NAME:
			szText = currentRequest.szUserName;
			break;
		case USR_COMPANY:
			szText = currentRequest.szUserCompany;
			break;
		}
		//Copy the text to the LV_ITEM structure
		//Maximum number of characters is in pItem->cchTextMax
		lstrcpyn( pItem->pszText, szText, pItem->cchTextMax );
	}

	// Does the list need image information?
	if( pItem->mask & LVIF_IMAGE ) 
	{
		TRACE( _T("IMAGE\n") );
		//// insert image
		//INT nImage = GetItemImage( nItemId, pItem->iSubItem );
		//// set image
		//if( nImage >= 0 )
		//	pItem->iImage = nImage;
	}

	// return
	*pResult = CDRF_DODEFAULT;
}

void CDlgPickUser::OnHdnItemclickListUsers(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);

	HDITEM hdi;
	CHeaderCtrl *pHeader = m_ctrlUsersList.GetHeaderCtrl();
	ASSERT( pHeader );

	// toggle sort
	if( m_nCurrentSort == phdr->iItem )
		m_bSortAscending = !m_bSortAscending;
	else
	{
		// set sort type
		m_bSortAscending = TRUE;
		// set header information
		memset( &hdi, NULL, sizeof( HDITEM ));
		pHeader->GetItem( m_nCurrentSort, &hdi );
		hdi.mask |= HDI_FORMAT;
		hdi.fmt |= HDF_STRING;
		pHeader->SetItem( m_nCurrentSort, &hdi );
	}
	// set current sort
	m_nCurrentSort = phdr->iItem;

	// check for sort
	switch( m_nCurrentSort )
	{
	case USR_ACTIVATED:
		m_szSort = _T("activated");
		break;
	case USR_EMAIL:
		m_szSort = _T("email");
		break;
	case USR_LAN_ID:
		m_szSort = _T("lan_id");
		break;
	case USR_NAME:
		m_szSort = _T("name");
		break;
	case USR_COMPANY:
		if( m_nType == PICK_TYPE_STAFF )
			m_szSort = _T("library_id");
		else
			m_szSort = _T("company");
		break;
	default:
		*pResult = 0;
		return;
	}

	// set sort type
	if( m_bSortAscending )
		m_szSort += _T(" ASC");
	else
		m_szSort += _T(" DESC");

	// set header information
	if( m_nCurrentSort > 0 )
	{
		memset( &hdi, NULL, sizeof( HDITEM ));
		pHeader->GetItem( m_nCurrentSort, &hdi );
		hdi.mask |= HDI_FORMAT;
		if( m_bSortAscending )
			hdi.fmt |= HDF_STRING | HDF_SORTUP;
		else
			hdi.fmt |= HDF_STRING | HDF_SORTDOWN;
		pHeader->SetItem( m_nCurrentSort, &hdi );
	}

	// fill list
	FillList();

	// retrun
	*pResult = 0;
}

void CDlgPickUser::OnLvnOdfinditemListUsers(NMHDR *pNMHDR, LRESULT *pResult)
{
	// pNMHDR has information about the item we should find
    // In pResult we should save which item that should be selected
	LPNMLVFINDITEM pFindInfo = reinterpret_cast<LPNMLVFINDITEM>(pNMHDR);

    /*
		pFindInfo->iStart is from which item we should search.
		We search to bottom, and then restart at top and will stop
		at pFindInfo->iStart, unless we find an item that match
	*/

    // Set the default return value to -1 that means we didn't find any match.
    *pResult = -1;

    //Is search NOT based on string?
    if(( pFindInfo->lvfi.flags & LVFI_STRING ) == 0 )
    {
        //This will probably never happend...
        return;
    }

    //This is the string we search for
	CString szSearch = pFindInfo->lvfi.psz;

	TRACE(_T("Find %s on %d\n"), szSearch, m_nCurrentSort);

    INT startPos = pFindInfo->iStart;
    //Is startPos outside the list (happens if last item is selected)
    if( startPos >= m_ctrlUsersList.GetItemCount() )
        startPos = 0;

	PICKLIST currentRequest;
	INT currentPos = startPos;
	INT nColumn = m_nCurrentSort;

	// search
    do
    {
		// get record
		currentRequest = m_aPickList.GetAt( currentPos );

		// find in column
		switch( nColumn )
		{
		case USR_EMAIL:
			{
				// search the email column
				if( szSearch.CompareNoCase( currentRequest.szUserEmail.Left( szSearch.GetLength() )) == 0 )
				{
					//Select this item and stop search.
					*pResult = currentPos;
					return;
				}
			}
			break;
		case USR_LAN_ID:
			{
				// search the email column
				if( szSearch.CompareNoCase( currentRequest.szUserLANID.Left( szSearch.GetLength() )) == 0 )
				{
					//Select this item and stop search.
					*pResult = currentPos;
					return;
				}
			}
			break;
		case USR_NAME:
			// search the date column
			if( szSearch.CompareNoCase( currentRequest.szUserName.Left( szSearch.GetLength() )) == 0 )
			{
				//Select this item and stop search.
				*pResult = currentPos;
				return;
			}
			break;
		case USR_COMPANY:
			// search the email column
			if( szSearch.CompareNoCase( currentRequest.szUserCompany.Left( szSearch.GetLength() )) == 0 )
			{
				//Select this item and stop search.
				*pResult = currentPos;
				return;
			}
			break;
		default:
			// search the email column
			if( szSearch.CompareNoCase( currentRequest.szUserEmail.Left( szSearch.GetLength() )) == 0 )
			{
				//Select this item and stop search.
				*pResult = currentPos;
				return;
			}
			break;
		}

        //Go to next item
        currentPos++;

        //Need to restart at top?
        if( currentPos >= m_ctrlUsersList.GetItemCount() )
            currentPos = 0;
    }
    //Stop if back to start
	while( currentPos != startPos );
}

void CDlgPickUser::FillList()
{
	// show wait
	CWaitCursor wait;

	INT nItem = 0;
	CString szTemp;
	PICKLIST List;

	// clear lists
	m_ctrlUsersList.DeleteAllItems();
	m_aPickList.RemoveAll();

	if( m_nType == PICK_TYPE_STAFF )
	{
		CArray<STAFF_LOOKUP> aStaff;
		CStringArray szaLibrary;

		// get staff
		appConfig.m_SQL.GetDescriptionStaffs( &aStaff, m_szSort, m_szFilter, FALSE );

		// get libraries
		appConfig.m_SQL.GetDescriptions( CMySQLEx::library, &szaLibrary );

		// loop and fill
		for( LONG nIndex = 0; nIndex < aStaff.GetCount(); nIndex++ )
		{
			// get staff
			STAFF_LOOKUP Staff;
			Staff = aStaff.GetAt( nIndex );

			// fill array
			List.nUserID = Staff.nStaffID;
			List.nActivated = Staff.nStaffLevel;
			List.szUserName = Staff.szStaffName;
			List.szUserEmail = Staff.szStaffEmail;
			List.szUserCompany = szaLibrary.GetAt( Staff.nLibraryID );
			// add to array
			m_aPickList.Add( List );
		}
	}
	else if( m_nType == PICK_TYPE_ILL )
	{
		CArray<EXTERNAL_ILL_SET> aUser;

		// get user
		appConfig.m_SQL.GetExternIllSet( &aUser, m_szFilter, m_szSort );

		// loop and fill
		for( LONG nIndex = 0; nIndex < aUser.GetCount(); nIndex++ )
		{
			// get staff
			EXTERNAL_ILL_SET User;
			User = aUser.GetAt( nIndex );

			// fill array
			List.nUserID = User.m_id;
			List.nActivated = 1;
			List.szUserName = _T("");
			List.szUserEmail = User.m_email;
			List.szUserCompany = User.m_company;

			// add to array
			m_aPickList.Add( List );
		}
	}
	else
	{
		CArray<USER_SET> aUser;
		CStringArray szaLibrary;

		// get user
		appConfig.m_SQL.GetUserSet( &aUser, m_szFilter, m_szSort );

		// get libraries
		appConfig.m_SQL.GetDescriptions( CMySQLEx::library, &szaLibrary );

		// loop and fill
		for( LONG nIndex = 0; nIndex < aUser.GetCount(); nIndex++ )
		{
			// get staff
			USER_SET User;
			User = aUser.GetAt( nIndex );

			// fill array
			List.nUserID = User.m_id;
			List.nActivated = User.m_activated;
			List.szUserName = User.m_name;
			List.szUserEmail = User.m_email;
			List.szUserLANID = User.m_lan_id;
			List.szUserCompany = User.m_company;

			// add to array
			m_aPickList.Add( List );
		}
	}

	// set item count
	m_ctrlUsersList.SetItemCountEx( m_aPickList.GetCount(), LVSICF_NOINVALIDATEALL | LVSICF_NOSCROLL );
}

void CDlgPickUser::OnBnClickedButtonAddUser()
{
	// add user
	if( appConfig.m_LDAP.bUseLDAPLogons )
	{
		CDlgAddLDAPUser dlgAddUser;
		if( dlgAddUser.DoModal() == IDOK )
		{
			// write history if added
			if( dlgAddUser.m_nUserID >= 0 )
				appConfig.UpdateUserHistory( dlgAddUser.m_nUserID, _T("Added by staff") );
			// set user data
			m_szEmail = dlgAddUser.m_szEmail;
			m_szName = dlgAddUser.m_szName;
			m_szCompany = dlgAddUser.m_szCompany;
			// end dialog;
			EndDialog( IDOK );
		}
	}
	else
	{
		CDlgEditUser dlgEditUser;
		// set add
		dlgEditUser.m_bAddUser = TRUE;
		// show dialog
		if( dlgEditUser.DoModal() == IDOK )
		{
			// write history
			appConfig.UpdateUserHistory( dlgEditUser.m_nUserID, _T("Added by staff") );
		}
	}
}

INT CDlgPickUser::SetDefaultButton(const DWORD nNewId) 
{
	DWORD nPrevId;

	nPrevId  = GetDefID();
	// Its not automatic - we have to remove the border from the old button
	SendDlgItemMessage(nPrevId, BM_SETSTYLE, BS_PUSHBUTTON, (LPARAM)TRUE);

	SetDefID(nNewId);
	// Likewise, add a border to the new one
	SendDlgItemMessage(nNewId, BM_SETSTYLE, BS_DEFPUSHBUTTON, (LPARAM)TRUE);

	return nPrevId;
}
